package com.example.zxx.springboot3.util;

import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * IThrowableUtil:异常工具类
 *
 * @author zhangxiaoxiang
 * @date 2022年2月4日
 */
public interface IThrowableUtil {

    IThrowableUtil BUILD = new IThrowableUtil() {
    };

    /**
     * 根据条件判断是否需要抛出异常[比如业务异常]
     *
     * @param before 处理逻辑,比如记录日志等
     * @param rule   判断条件
     * @param re     异常类型
     * @param <RE>   异常
     */
    default <RE extends RuntimeException> void throwOf(Consumer<RE> before, boolean rule, RE re) {
        if (rule) {
            before.accept(re);
            throw re;
        }
    }


    /**
     * 满足条件抛异常
     *
     * @param rule 条件
     * @param re   异常类型
     * @param <RE> 异常
     */
    default <RE extends RuntimeException> void throwOf(boolean rule, RE re) {
        throwOf(e -> {
        }, rule, re);
    }

    /**
     * 根据条件抛出自定义异常信息描述
     *
     * @param errMessage 异常信息
     * @param object     发生异常的对象
     * @param rule       判断规则
     * @param <T>        发生异常的对象类型
     */
    default <T> void throwOf(String errMessage, T object, Predicate<T> rule) {
        throwOf(new RuntimeException(errMessage), object, rule);
    }

    default <T> void throwOf(Consumer<RuntimeException> before, String errMessage, T object, Predicate<T> rule) {
        throwOf(before, rule, new RuntimeException(errMessage), object);
    }

    default <RE extends RuntimeException, T> void throwOf(RE re, T object, Predicate<T> rule) {
        throwOf(rule.test(object), re);
    }

    default <RE extends RuntimeException, T> void throwOf(Consumer<RE> before, Predicate<T> rule, RE re, T object) {
        throwOf(before, rule.test(object), re);
    }

    default <T> void throwofNon(String errMessage, T object, Predicate<T> rule) {
        throwofNon(new RuntimeException(errMessage), object, rule);
    }

    default <T> void throwofNon(Consumer<RuntimeException> before, String errMessage, T object, Predicate<T> rule) {
        throwofNon(before, new RuntimeException(errMessage), object, rule);
    }

    default <RE extends RuntimeException, T> void throwofNon(RE re, T object, Predicate<T> rule) {
        throwOf(!rule.test(object), re);
    }

    default <RE extends RuntimeException, T> void throwofNon(Consumer<RE> before, RE re, T object, Predicate<T> rule) {
        throwOf(before, !rule.test(object), re);
    }

    default void throwOf(boolean rule, String errMessage) {
        throwOf(rule, new RuntimeException(errMessage));
    }

    default void throwOf(Consumer<RuntimeException> before, String errMessage, boolean rule) {
        throwOf(before, rule, new RuntimeException(errMessage));
    }

    default void throwOf(String errMessage, Supplier<Boolean> rule) {
        throwOf(rule.get(), new RuntimeException(errMessage));
    }

    default void throwOf(Consumer<RuntimeException> before, String errMessage, Supplier<Boolean> rule) {
        throwOf(before, rule.get(), new RuntimeException(errMessage));
    }

    default <RE extends RuntimeException> void throwOf(Supplier<Boolean> rule, RE re) {
        throwOf(rule.get(), re);
    }

    default <RE extends RuntimeException> void throwOf(Consumer<RE> before, Supplier<Boolean> rule, RE re) {
        throwOf(before, rule.get(), re);
    }

}